#include "RendererWin32.h"
#include "Game.h"
#include <assert.h>

Renderer::Renderer (HWND hWnd)
{
	pVertexBuffer = NULL;/**/
	colVertexBuffer = NULL;
	texVertexBuffer = NULL;
	winHandle = &hWnd;

	if(winHandle == NULL)
	{
		//fuck
		assert(false);
		throw;
	}

	viewerPos.x = -300;
	viewerPos.y = 0;
	viewerPos.z = -10;

	D3DPRESENT_PARAMETERS PresentParams;
	memset(&PresentParams, 0, sizeof(D3DPRESENT_PARAMETERS));

	PresentParams.Windowed = TRUE;
	PresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;

	IDirect3D9* direct3DCosa = Direct3DCreate9(D3D_SDK_VERSION);

	if(direct3DCosa == NULL)
	{
		//fuck
		assert(false);
		throw;
	}
	if(direct3DCosa->CreateDevice(D3DADAPTER_DEFAULT,
		D3DDEVTYPE::D3DDEVTYPE_HAL, *winHandle, D3DCREATE_HARDWARE_VERTEXPROCESSING, 
		&PresentParams,&graphCardHandle) != D3D_OK)
	{
		if(direct3DCosa->CreateDevice(D3DADAPTER_DEFAULT,
			D3DDEVTYPE::D3DDEVTYPE_HAL, *winHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
			&PresentParams,&graphCardHandle) != D3D_OK)
		{
			//fuck
			assert(false);
			throw;
		}
	}
	
	if(graphCardHandle == NULL)
	{
		//shit
		assert(false);
		throw;
	}

	graphCardHandle->SetRenderState(D3DRS_LIGHTING, FALSE);
	//m_pkDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
	graphCardHandle->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
	graphCardHandle->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	graphCardHandle->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	graphCardHandle->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	graphCardHandle->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
	graphCardHandle->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);

	setViewportPosition();

	D3DVIEWPORT9 viewport;
	if(graphCardHandle->GetViewport(&viewport) != D3D_OK)
	{
		assert(false);
		throw;
	}

	D3DXMatrixOrthoLH(&projectionMatrix, (float) viewport.Width, (float) viewport.Height, -25, 25);
	if( graphCardHandle->SetTransform(D3DTS_PROJECTION, &projectionMatrix) != D3D_OK)
	{
		assert(false);
		throw;
	}

	
	loadIdentity();
	Timer::getInstance();
}

Renderer::~Renderer()
{
	if(graphCardHandle)
	{
		if(colVertexBuffer != NULL)
		{
			colVertexBuffer->Release();
			delete colVertexBuffer;
		}

		if(texVertexBuffer != NULL)
		{
			texVertexBuffer->Release();
			delete texVertexBuffer;
		}

		IDirect3D9* direct3DCosa;
		graphCardHandle->GetDirect3D(&direct3DCosa);
		graphCardHandle->Release();
		direct3DCosa->Release();
		Timer::destroyInstance();
	}
}

void Renderer::Draw(COL_VERTEX* vertexCollection, unsigned int uiVertexCount, DrawPrimitives ePrim)
{
	
	if(colVertexBuffer == NULL)
	{
		colVertexBuffer = new VertexBuffer<COL_VERTEX, D3DFVF_XYZRHW|D3DFVF_DIFFUSE>();
		colVertexBuffer->Create(graphCardHandle, false);
	}
	
	//colVertexBuffer->Bind();
	colVertexBuffer->Draw(vertexCollection, (D3DPRIMITIVETYPE)ePrim, uiVertexCount);
	/**/
}

void Renderer::Draw(TEX_VERTEX* vertexCollection, unsigned int uiVertexCount, DrawPrimitives ePrim)
{
	
	if(texVertexBuffer == NULL)
	{
		texVertexBuffer = new VertexBuffer<TEX_VERTEX, D3DFVF_XYZ|D3DFVF_TEX1|D3DFVF_TEXCOORDSIZE2(0)>();
		texVertexBuffer->Create(graphCardHandle, false);
	}
	
	//colVertexBuffer->Bind();
	texVertexBuffer->Draw(vertexCollection, (D3DPRIMITIVETYPE)ePrim, uiVertexCount);
	/**/
}

void Renderer::StartFrame()
{
	Timer::instance->Measure();
	graphCardHandle->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 
										1.0f, 0);
	if( FAILED( graphCardHandle->BeginScene() ) )
	{
		//fuck
		assert(false);
		throw;
	}
}

void Renderer::EndFrame()
{
	if( FAILED( graphCardHandle->EndScene() ) )
	{
		assert(false);
		throw;
	}
	graphCardHandle->Present(NULL, NULL, NULL, NULL);

	//if(colVertexBuffer) colVertexBuffer->Release();
	//pVertexObject->Release();
}

void Renderer::loadIdentity()
{
	D3DXMATRIX tempMat;
	D3DXMatrixIdentity(&tempMat);
	if(matrixMode == View)
	{
		D3DXVECTOR3 eyePos(0,0,-1);
		D3DXVECTOR3 lookPos(0,0,0);
		D3DXVECTOR3 upVector(0,1,0);

		D3DXMatrixLookAtLH(&tempMat, &eyePos, &lookPos, &upVector);
	}

	graphCardHandle->SetTransform((D3DTRANSFORMSTATETYPE)matrixMode, &tempMat);


}

void Renderer::setMatrixMode(Matrix_Mode mode)
{
	matrixMode = mode;
}

void Renderer::setViewportPosition()
{
	D3DXMATRIX mat;
	D3DXVECTOR3 lookPos;

	lookPos.x = viewerPos.x;
	lookPos.y = viewerPos.y;
	lookPos.z = 0.0f;

	D3DXMatrixLookAtLH(&mat, &viewerPos, &lookPos, &viewerUp);
	if(graphCardHandle->SetTransform((D3DTRANSFORMSTATETYPE)View, &mat) == D3D_OK)
	{
		viewerMatrix = mat;
	}
	else
	{
		MessageBox(*winHandle,"viewport fuck","fuck",MB_OK);
	}
}

void Renderer::Translate(float x, float y, float z)
{
	D3DXMATRIX tempMat;

	D3DXMatrixTranslation(&tempMat, x, y, z);

	graphCardHandle->MultiplyTransform((D3DTRANSFORMSTATETYPE)matrixMode, &tempMat);
}

void Renderer::Scale(float x, float y)
{
	D3DXMATRIX tempMat;

	D3DXMatrixScaling(&tempMat, x, y, 1);

	graphCardHandle->MultiplyTransform((D3DTRANSFORMSTATETYPE)matrixMode, &tempMat);
}

void Renderer::RotateX(float angle)
{
	D3DXMATRIX tempMat;

	D3DXMatrixRotationX(&tempMat, angle);

	graphCardHandle->MultiplyTransform((D3DTRANSFORMSTATETYPE)matrixMode, &tempMat);
}

void Renderer::RotateY(float angle)
{
	D3DXMATRIX tempMat;

	D3DXMatrixRotationY(&tempMat, angle);

	graphCardHandle->MultiplyTransform((D3DTRANSFORMSTATETYPE)matrixMode, &tempMat);
}
void Renderer::RotateZ(float angle)
{
	D3DXMATRIX tempMat;

	D3DXMatrixRotationZ(&tempMat, angle);

	graphCardHandle->MultiplyTransform((D3DTRANSFORMSTATETYPE)matrixMode, &tempMat);
}

void Renderer::bindTexture(tex_ptr* tex)
{
	IDirect3DTexture9 * texture = textureMap[*tex->get()->getFilename()];

	assert(texture);

	if(graphCardHandle->SetTexture(0, texture) != D3D_OK)
		assert(false);
}
void Renderer::unBindTexture()
{
	graphCardHandle->SetTexture(0, NULL);
}

bool Renderer::loadTexture(tex_ptr* texture)
{
	IDirect3DTexture9* bitmap = NULL;
	D3DXIMAGE_INFO imgInfo;

	DWORD color;

	color = texture->get()->getColorKey();
	
	if(D3DXCreateTextureFromFileEx(graphCardHandle, texture->get()->getFilename()->c_str(), 0,0,0,0, 
									D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 
									color, &imgInfo, NULL, &bitmap))
	{
		assert(false);
		return false;
	}

	texture->get()->setHeight(imgInfo.Height);
	texture->get()->setWidth(imgInfo.Width);
	
	textureMap[*texture->get()->getFilename()] = bitmap;
}